package org.bpms.plugins.upload;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Random;

import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
import com.jfinal.core.Controller;
import com.jfinal.core.JFinal;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.PropKit;
import com.jfinal.upload.UploadFile;

/**
 * 文件上传控制器
 * @author hupei
 *
 */
public class FileUploadController extends Controller {
	//上传目录
	private static final String UPLOAD_PATH = PropKit.use("config.properties").get("uploadpath");
	
	/**
	 * 普通文件上传
	 * @throws IOException 
	 */
	public void simpleUpload() throws IOException{
		Map result = new HashMap();
		String realPath = PathKit.getWebRootPath()+"/"+UPLOAD_PATH+"/"+date_url();
		File uploadDir = new File(realPath);// 创建要上传文件到指定的目录
		if (!uploadDir.exists()){
			uploadDir.mkdirs();
		}
		
		UploadFile uf = getFile("simplefile", realPath);
		String affix_id = "";
		String affix_name = "";
        if (null != uf){
        	affix_name = uf.getFile().getName();
        	File file = uf.getFile();
        	String fileExt = affix_name.substring(affix_name.lastIndexOf(".") + 1);
        	String dateStr = String.format("%1$tY%<tm%<td%<tH%<tM%<tS", Calendar.getInstance());
			affix_id = dateStr + "_" + new Random().nextInt(1000) + "." + fileExt;
			File savefile = new File(new File(realPath), affix_id);
			copy(file, savefile);
			if (file.exists()){
				file.delete();
			}
			result.put("error", 0);
			result.put("name", affix_name);
			result.put("url", JFinal.me().getContextPath() + "/" +UPLOAD_PATH + "/" + affix_id);
        }else{
        	result.put("error", 1);
        	result.put("message", "请选择文件");
        }
        renderJson(result);
	}
	
	/**
	 * kindeditor文件上传
	 * @throws Exception
	 */
	public void upload() throws Exception {
		// 定义允许上传的文件扩展名
		HashMap<String, String> extMap = new HashMap<String, String>() {
			private static final long serialVersionUID = 1L;
			{
				put("image", "gif,jpg,jpeg,png,bmp");
				put("flash", "swf,flv");
				put("media", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb,mp4");
				put("file", "doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2");
			}
		};

		Map result = new HashMap();
		String dirName = getPara("dir") == null ? "image" : getPara("dir");
		String realPath = PathKit.getWebRootPath()+"/"+UPLOAD_PATH+"/"+date_url();
		
		File uploadDir = new File(realPath);// 创建要上传文件到指定的目录
		if (!uploadDir.exists()){
			uploadDir.mkdirs();
		}
		UploadFile uf = getFile("imgFile", realPath);
		String affix_id = "";
		String affix_name = "";
		if (uf != null) {
			affix_name = uf.getFile().getName();
			File file = uf.getFile();
			// 检查扩展名
			String fileExt = affix_name.substring(affix_name.lastIndexOf(".") + 1).toLowerCase();
			if (!Lists.newArrayList(Splitter.on(",").split(extMap.get(dirName))).contains(fileExt)) {
				result.put("error", 1);
				result.put("message", "上传文件扩展名是不允许的扩展名。\n只允许" + extMap.get(dirName) + "格式。");
				file.delete();
			} else {
				// yyyyMMddHHmmss
				String dateStr = String.format("%1$tY%<tm%<td%<tH%<tM%<tS", Calendar.getInstance());
				affix_id = dateStr + "_" + new Random().nextInt(1000) + "." + fileExt;
				File savefile = new File(new File(realPath), affix_id);
				copy(file, savefile);
				if (file.exists()) {
					file.delete();
				}
				result.put("error", 0);
				result.put("url", JFinal.me().getContextPath() + "/" +UPLOAD_PATH +"/" + date_url() + "/" + affix_id);
			}
		} else {
			result.put("error", 1);
			result.put("message", "请选择文件");
		}

		renderJson(result);
	}
	
	/**
	 * 文件管理
	 */
	public void filemanager() {
		String[] fileTypes = new String[] { "gif", "jpg", "jpeg", "png", "bmp" };
		String currentPath = PathKit.getWebRootPath()+"/"+UPLOAD_PATH+"/" + date_url();
		File currentPathFile = new File(currentPath);
		final List<Hashtable> fileList = new ArrayList<Hashtable>();
		if (currentPathFile.listFiles() != null) {
			for (File file : currentPathFile.listFiles()) {
				Hashtable<String, Object> hash = new Hashtable<String, Object>();
				String fileName = file.getName();
				if (file.isDirectory()) {
					hash.put("is_dir", true);
					hash.put("has_file", (file.listFiles() != null));
					hash.put("filesize", 0L);
					hash.put("is_photo", false);
					hash.put("filetype", "");
				} else if (file.isFile()) {
					String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
					hash.put("is_dir", false);
					hash.put("has_file", false);
					hash.put("filesize", file.length());
					hash.put("is_photo", Arrays.<String> asList(fileTypes).contains(fileExt));
					hash.put("filetype", fileExt);
				}
				hash.put("filename", fileName);
				hash.put("datetime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(file.lastModified()));
				fileList.add(hash);
			}
		}
		// 排序形式，name or size or type
		String order = getPara("order") != null ? getPara("order").toLowerCase() : "name";
		if ("size".equals(order)) {
			Collections.sort(fileList, new SizeComparator());
		} else if ("type".equals(order)) {
			Collections.sort(fileList, new TypeComparator());
		} else {
			Collections.sort(fileList, new NameComparator());
		}

		Map<String, Object> result = new HashMap<String, Object>() {
			private static final long serialVersionUID = 1L;
			{
				put("moveup_dir_path", "");
				put("current_dir_path", "");
				put("current_url", JFinal.me().getContextPath() +"/"+UPLOAD_PATH +"/" + date_url());
				put("total_count", fileList.size());
				put("file_list", fileList);
			}
		};
		renderJson(result);
	}
	
	public class NameComparator implements Comparator {
		public int compare(Object a, Object b) {
			Hashtable hashA = (Hashtable) a;
			Hashtable hashB = (Hashtable) b;
			if (((Boolean) hashA.get("is_dir")) && !((Boolean) hashB.get("is_dir"))) {
				return -1;
			} else if (!((Boolean) hashA.get("is_dir")) && ((Boolean) hashB.get("is_dir"))) {
				return 1;
			} else {
				return ((String) hashA.get("filename")).compareTo((String) hashB.get("filename"));
			}
		}
	}

	public class SizeComparator implements Comparator {
		public int compare(Object a, Object b) {
			Hashtable hashA = (Hashtable) a;
			Hashtable hashB = (Hashtable) b;
			if (((Boolean) hashA.get("is_dir")) && !((Boolean) hashB.get("is_dir"))) {
				return -1;
			} else if (!((Boolean) hashA.get("is_dir")) && ((Boolean) hashB.get("is_dir"))) {
				return 1;
			} else {
				if (((Long) hashA.get("filesize")) > ((Long) hashB.get("filesize"))) {
					return 1;
				} else if (((Long) hashA.get("filesize")) < ((Long) hashB.get("filesize"))) {
					return -1;
				} else {
					return 0;
				}
			}
		}
	}

	public class TypeComparator implements Comparator {
		public int compare(Object a, Object b) {
			Hashtable hashA = (Hashtable) a;
			Hashtable hashB = (Hashtable) b;
			if (((Boolean) hashA.get("is_dir")) && !((Boolean) hashB.get("is_dir"))) {
				return -1;
			} else if (!((Boolean) hashA.get("is_dir")) && ((Boolean) hashB.get("is_dir"))) {
				return 1;
			} else {
				return ((String) hashA.get("filetype")).compareTo((String) hashB.get("filetype"));
			}
		}
	}
	
	private String date_url(){
		SimpleDateFormat yearDf = new SimpleDateFormat("yyyy");
		SimpleDateFormat monthDf = new SimpleDateFormat("MM");
		SimpleDateFormat dateDf = new SimpleDateFormat("dd");
		Date date = new Date();
		String ymd = yearDf.format(date) + "/" + monthDf.format(date) + "/" + dateDf.format(date) + "/";
		return ymd;
	}
	
	private void copy(File from , File to){
		try{
			int byteread = 0;
			InputStream instream = new FileInputStream(from);
			FileOutputStream fs = new FileOutputStream(to);
			byte[] buffer = new byte[1024];
			while((byteread = instream.read(buffer)) != -1){
				fs.write(buffer, 0, byteread);
			}
			instream.close();
			fs.close();
		}catch(Exception e){
			e.printStackTrace();
		}
	}

}
